package com.zbs.framework.common.utils.mp;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.zbs.framework.swagger.utils.DateUtils;
import org.springframework.util.StringUtils;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 注解属性获取工具类
 * @author Zbs
 * @since 2022-04-18
 */
public class ColumnMpUtil {


    public static <T> String getTableName(Class<T> clazz) {
        TableName annotation = clazz.getAnnotation(TableName.class);
        String tableName;
        if (annotation != null && StringUtils.hasLength(annotation.value())) {
            tableName = annotation.value();
        } else {
            tableName = DateUtils.decamelize(clazz.getSimpleName());
        }
        return tableName;
    }

    private static <T> SerializedLambda getSerializedLambda(SFunction<T, ?> fn) {
        // 从function取出序列化方法
        Method writeReplaceMethod;
        try {
            writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        // 从序列化方法取出序列化的lambda信息
        boolean isAccessible = writeReplaceMethod.isAccessible();
        writeReplaceMethod.setAccessible(true);
        SerializedLambda serializedLambda;
        try {
            serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        writeReplaceMethod.setAccessible(isAccessible);
        // 从lambda信息取出method、field、class等
        return serializedLambda;
    }

    public static <T> String getTableName(SFunction<T, ?> fn) {
        SerializedLambda serializedLambda = getSerializedLambda(fn);
        // 从lambda信息取出method、field、class等
        Class<?> clazz;
        try {
            clazz = Class.forName(serializedLambda.getImplClass().replace("/", "."));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return getTableName(clazz);
    }

    public static <T> String getName(SFunction<T, ?> fn) {
        SerializedLambda serializedLambda = getSerializedLambda(fn);
        // 从lambda信息取出method、field、class等
        String fieldName = serializedLambda.getImplMethodName().substring("get".length());
        fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase());
        Field field;
        try {
            field = Class.forName(serializedLambda.getImplClass().replace("/", ".")).getDeclaredField(fieldName);
        } catch (ClassNotFoundException | NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        // 从field取出字段名，可以根据实际情况调整
        TableField jpaTableField = field.getAnnotation(TableField.class);
        if (jpaTableField != null && jpaTableField.value().length() > 0) {
            return jpaTableField.value();
        } else {
            return DateUtils.decamelize(fieldName);
        }
    }


}